package com.allwees.bs.core.modelbase.entity;

import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.allwees.bs.core.modelbase.bo.Bo;
import com.allwees.core.common.constant.EDelete;
import com.allwees.core.common.constant.EStatus;
import com.allwees.core.common.util.DateUtil;
import com.allwees.core.common.util.UuidUtil;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.PostRemove;
import javax.persistence.PrePersist;
import javax.persistence.PreRemove;
import javax.persistence.PreUpdate;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import java.util.Date;

/**
 * Entity基类
 *
 * @author yangylsky
 *
 */
@Data
@ToString
@Accessors(chain = true)
@MappedSuperclass
public abstract class BaseEntity implements Bo {

	private static final long serialVersionUID = 3608400552562551777L;

	public static final String[] fields = {"id", "uuid", "idx", "status", "createdAt", "updatedAt"};

	@Id
	@TableId(type = IdType.AUTO)
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@JsonIgnore
	protected Integer id;

	@TableField(fill = FieldFill.INSERT, updateStrategy = FieldStrategy.NEVER)
	@Column(updatable = false, length = 48)
	protected String uuid;

	@TableField(fill = FieldFill.INSERT)
	protected Integer status;

	@TableField(fill = FieldFill.INSERT)
	@Column(updatable = false)
	@Temporal(TemporalType.TIMESTAMP)
	protected Date createdAt;

	@TableField(fill = FieldFill.INSERT_UPDATE)
	protected Date updatedAt;

	@TableField(fill = FieldFill.INSERT)
	protected Integer idx;

	// 是否删除
	@JsonIgnore
	@TableLogic(value = "0", delval = "1")
	@TableField(fill = FieldFill.INSERT)
	@Column(columnDefinition = "INT1 UNSIGNED")
	protected Integer isDeleted;

	//删除时间
	@JsonIgnore
	protected Date deletedAt;

	@PrePersist
	public void onCreate() {
		if(this.createdAt == null) {
			this.createdAt = DateUtil.now();
		}
		if(StringUtils.isBlank(uuid)) {
			this.uuid = UuidUtil.generate();
		}
		if(this.status == null) {
			this.status = EStatus.NORMAL.value();
		}
		if(this.idx == null) {
			this.idx = 0;
		}
		this.isDeleted = EDelete.UNDELETED.value();
	}

	@PreUpdate
	public void onUpdate() {
		if(this.updatedAt == null) {
			this.updatedAt = DateUtil.now();
		}
	}

	@PreRemove
	@PostRemove
	public void onDelete() {
		if(this.deletedAt == null) {
			this.deletedAt = DateUtil.now();
		}
		this.isDeleted = EDelete.DELETED.value();
	}

	public String getStatusDesc() {
		return status != null ? getEStatus().desc() : "";
	}

	@JsonIgnore
    @JSONField(serialize = false)
	public boolean isNormal() {
		return isNormal(getStatus());
	}

	public Boolean canEdit() {
		return null;
	}

	public Boolean isEditing() {
		return null;
	}

	public static boolean isNormal(Integer status) {
		return status != null && status.equals(EStatus.NORMAL.value());
	}

	@JsonIgnore
    @JSONField(serialize = false)
	public EStatus getEStatus() {
		if(status == null){
			return null;
		}
		return EStatus.byValue(status);
	}

	@JsonIgnore
    @JSONField(deserialize = false)
	public void setEStatus(EStatus status) {
		this.status = status.value();
	}

	public void assertStatus(EStatus... status) {
		Assert.notEmpty(status, "status cannot be a null");
		Assert.isTrue(ArrayUtils.contains(status, getEStatus()), "invalid status [" + getEStatus() + "]");
	}
}
